package sample.util;

import java.io.IOException;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;


public class ConventionUtils {
    
	/**
	 * Sorta.. Algo:
	 * Action -- setSampleService ---- ignore
	 * 		  -- setAnotherService
	 * SampleServiceImpl -- setAnotherService  -- sampleService --> SampleServiceImpl (anotherService, sampleDao) 
	 * 						setSampleDao
	 * AnotherServiceImpl -- setAnotherDao  -- anotherService --> AnotherServiceImpl (anotherDao)
	 * SampleDaoImpl -- setAnotherDao -- sampleDao --> SampleDaoImpl (anotherDao)
	 * AnotherDaoImpl --> anotherDao -- AnotherDaoImpl
	 */
	
	public static List getBeanMatches(Properties prop) {
        List beanMatches = new ArrayList();

        String packageNames = prop.getProperty(Constants.CONVENTION_INCLUDE_PACKAGES);
        List<String> includePackages = getListFromCsv(packageNames);

        String methodNameBeginsWith = prop.getProperty(Constants.CONVENTION_INJECT_METHOD_NAME_BEGINS_WITH);
        String methodNameEndsWith = prop.getProperty(Constants.CONVENTION_INJECT_METHOD_NAME_ENDS_WITH);

        List<String> methodPatterns = generateMethodPatterns(methodNameBeginsWith,
                methodNameEndsWith);

        String beanNameEndsWith = prop.getProperty(Constants.CONVENTION_BEAN_NAME_ENDS_WITH);
        List<String> beanNameEndsWithList = getListFromCsv(beanNameEndsWith);

        System.out.println("include packs >> " + includePackages);
        System.out.println("include methodPatterns >> " + methodPatterns);
        System.out.println("beanNameEndsWithList >> " + beanNameEndsWithList);

        for (Iterator<String> iter = includePackages.iterator();
                iter.hasNext();) {
            Class[] classesInPackage = ReflectionUtils.getClassesInPackage((String) iter.next());

            beanMatches.add(ReflectionUtils.getBeanMatch(
                    classesInPackage, beanNameEndsWithList, methodPatterns));
        }

        return beanMatches;
    }

    private static List<String> generateMethodPatterns(
        String methodNameBeginsWith, String methodNameEndsWith) {
        List<String> methodNameEndsWithList = getListFromCsv(methodNameEndsWith);

        List methodPatterns = new ArrayList();

        for (Iterator iter = methodNameEndsWithList.iterator(); iter.hasNext();) {
            methodPatterns.add(methodNameBeginsWith + ".*" +
                (String) iter.next());
        }

        return methodPatterns;
    }

    private static List<String> getListFromCsv(String csv) {
        List<String> values = new ArrayList<String>();

        StringTokenizer tokenizer = new StringTokenizer(csv, ",");

        while (tokenizer.hasMoreTokens()) {
            values.add(tokenizer.nextToken());
        }

        return values;
    }

    public static Properties getConfigProperties() {
        Properties prop = new Properties();

        try {
            prop.load(Thread.currentThread().getContextClassLoader()
                            .getResourceAsStream(Constants.CONVENTION_CONFIG_FILE));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(
                "Error initializing the config for convention! Unable to load file " +
                Constants.CONVENTION_CONFIG_FILE + " from classpath");
        }

        return prop;
    }
}
